/**
 * Test of Closure function
 *
 * author: Marcin Wachulski
 *
 */
#include "KOVTest.h"

// checks whether all elements in sub set are included within super set
bool subsumes(AttributeSet *sub, AttributeSet *super) {
    for (std::set<Attribute>::iterator i = sub->data.begin();
        i != sub->data.end(); i++)
        if (super->data.find(*i) == super->data.end())
            return false;
    return true;
}

class ClosureTest : public testing::Test {
protected:
    virtual void SetUp() {
        AttributeSet *attrSet;
        ObjectSet *objSet;

        attrSet = new AttributeSet();
        attrSet->data.insert(1);
        objSet = new ObjectSet();
        for (int i = 1; i <= 1; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        attrSet = new AttributeSet();
        attrSet->data.insert(2);
        objSet = new ObjectSet();
        for (int i = 1; i <= 2; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        attrSet = new AttributeSet();
        attrSet->data.insert(3);
        objSet = new ObjectSet();
        for (int i = 1; i <= 3; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        attrSet = new AttributeSet();
        attrSet->data.insert(4);
        objSet = new ObjectSet();
        for (int i = 1; i <= 4; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        fc.processedNo = 4;

        attrSet = new AttributeSet();
        attrSet->data.insert(5);
        objSet = new ObjectSet();
        for (int i = 1; i <= 5; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        attrSet = new AttributeSet();
        attrSet->data.insert(6);
        objSet = new ObjectSet();
        for (int i = 1; i <= 6; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        attrSet = new AttributeSet();
        attrSet->data.insert(7);
        objSet = new ObjectSet();
        for (int i = 1; i <= 7; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        attrSet = new AttributeSet();
        attrSet->data.insert(6);
        attrSet->data.insert(7);
        attrSet->data.insert(9);
        objSet = new ObjectSet();
        for (int i = 1; i <= 8; i++)
            objSet->data.insert(i);
        fc.data.push_back(OAPair(objSet, attrSet));

        for (int i = 1; i <= 15; i++)
            all_attributes.data.insert(i);
    }

    FormalContext fc;
    AttributeSet all_attributes;
};

TEST_F(ClosureTest, empty_FC) {
    FormalContext empty_fc;
    AttributeSet *attrSet = new AttributeSet();
    ObjectSet *objSet = new ObjectSet();

    ClosureForEmptySet(all_attributes, OAPair(objSet, attrSet), empty_fc);

    EXPECT_EQ(15, attrSet->data.size());
    subsumes(&all_attributes, attrSet);
    EXPECT_EQ(8, fc.data.size());
    EXPECT_EQ(4, fc.processedNo);
    EXPECT_TRUE(is_sorted(fc));
    delete attrSet;
    delete objSet;
}

TEST_F(ClosureTest, nonequal_support) {
    AttributeSet *attrSet = new AttributeSet();
    attrSet->data.insert(1);
    attrSet->data.insert(2);
    attrSet->data.insert(3);
    ObjectSet *objSet = new ObjectSet();

    ClosureForEmptySet(all_attributes, OAPair(objSet, attrSet), fc);

    EXPECT_EQ(7, attrSet->data.size());
    AttributeSet diff_attributes;
    diff_attributes.data.insert(8);
        for (int i = 10; i <= 15; i++)
            diff_attributes.data.insert(i);
    subsumes(&diff_attributes, attrSet);
    EXPECT_EQ(8, fc.data.size());
    EXPECT_EQ(4, fc.processedNo);
    EXPECT_TRUE(is_sorted(fc));
    delete attrSet;
    delete objSet;
}

TEST_F(ClosureTest, full_processing) {
    AttributeSet *attrSet = new AttributeSet();
    attrSet->data.insert(1);
    attrSet->data.insert(2);
    attrSet->data.insert(3);
    attrSet->data.insert(4);
    attrSet->data.insert(5);
    attrSet->data.insert(1001);
    ObjectSet *objSet = new ObjectSet();
    objSet->data.insert(3);
    objSet->data.insert(4);
    objSet->data.insert(5);
    objSet->data.insert(6);
    objSet->data.insert(7);
    objSet->data.insert(8);
    objSet->data.insert(9);
    objSet->data.insert(10);

    AttributeSet last_attrSet_inFC = *(fc.data.back().second);
    OAPair oa(objSet, attrSet);

    ClosureForEmptySet(all_attributes, oa, fc);

    EXPECT_EQ(8, oa.second->data.size());
    AttributeSet diff_attributes;
    diff_attributes.data.insert(8);
        for (int i = 8; i <= 15; i++)
            diff_attributes.data.insert(i);
    subsumes(&diff_attributes, oa.second);
    subsumes(&last_attrSet_inFC, oa.second);
    EXPECT_EQ(7, fc.data.size());
    EXPECT_EQ(4, fc.processedNo);
    EXPECT_TRUE(is_sorted(fc));
    delete oa.first;
    delete oa.second;
}
